/*
 * DatagramBuilder Library: serialize/deserialize data to/from datagram
 * Copyright (C) 2008 Rakov Ilya <RakovIlya@gmail.com>
 *
 * This library can be distributed under the terms of the GNU LGPLv2.
 * See the file COPYING.LIB.
 */


#ifndef DATAGRAM_NETHOST_H_
#define DATAGRAM_NETHOST_H_


/**
 * @file NetHost.h
 *
 * @brief ToNet() and ToHost() header file
 *
 * @date Nov 28, 2008
 * @author Rakov Ilya
 */


#include <boost/type_traits.hpp>
#include <boost/static_assert.hpp>

#include <arpa/inet.h>


namespace implementation
{

template< class T > class Impl;

} // namespace implementation


/**
 * @brief Converts the integral data types from host byte order to network byte order
 *
 * Function is compatible with 1, 2, 4 bytes data types
 */
template< class T > inline T ToNet( const T &value )
{
  return implementation::Impl< T >::ToNet( value );
}


/**
 * @brief Converts the integral data types from network byte order to host byte order
 *
 * Function is compatible with 1, 2, 4 bytes data types
 */
template< class T > inline T ToHost( const T &value )
{
  return implementation::Impl< T >::ToHost( value );
}



namespace implementation
{

template< class T > class Impl
{

  BOOST_STATIC_ASSERT( boost::is_integral<T>::value );


  template< size_t v > struct Int2Type
  {
    enum { value_ = v };
  };


  static inline T ToNet( const T value, Int2Type< 1 > ) { return value; }
  static inline T ToNet( const T value, Int2Type< 2 > ) { return htons( value ); }
  static inline T ToNet( const T value, Int2Type< 4 > ) { return htonl( value ); }

  static inline T ToHost( const T value, Int2Type< 1 > ) { return value; }
  static inline T ToHost( const T value, Int2Type< 2 > ) { return ntohs( value ); }
  static inline T ToHost( const T value, Int2Type< 4 > ) { return ntohl( value ); }


public:

  /*
   * NOTE: compile-time error here means using incompatible type T
   */
  static inline T ToNet( const T value )
  {
    return ToNet( value, Int2Type< sizeof(T) >() );
  }


  /*
   * NOTE: compile-time error here means using incompatible type T
   */
  static inline T ToHost( const T value )
  {
    return ToHost( value, Int2Type< sizeof(T) >() );
  }

};


} // namespace implementation

#endif /* DATAGRAM_NETHOST_H_ */
